package org.fastsyncer.plugin.impl;

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.constant.ThirdpartyConstant;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.util.ApplicationUtil;
import org.fastsyncer.common.util.SHA1Util;
import org.fastsyncer.common.util.UUIDUtil;
import org.fastsyncer.plugin.AbstractConvert;
import org.fastsyncer.plugin.impl.pool.DatabasePool;
import org.fastsyncer.plugin.impl.util.PinyinUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * <ul>
 * <dt>港中旅帐号生成规则：</dt>
 *  <dl>
 *      <li>针对新增操作：</li>
 *      <li>&nbsp;&nbsp;1.将汉字转换为拼音,例如张三 >> zhangsan</li>
 *      <li>&nbsp;&nbsp;2.姓和名之间用.符号拼接,例如张三 >> zhang.san</li>
 *      <li>&nbsp;&nbsp;3.重复帐号后面自动拼接递增序号,例如张三 >> zhangsan1</li>
 *      <li>针对修改操作：</li>
 *      <li>&nbsp;&nbsp;1.修改后帐号不变,用历史帐号覆盖当前</li>
 *      <li>针对删除操作：</li>
 *      <li>&nbsp;&nbsp;1.直接删除</li>
 *  </dl>
 * </ul>
 * 
 * @author AE86
 * @date 2017年11月29日 下午15:56:44
 * @version 1.0.0
 */
public class HongKongAccountConvertImpl extends AbstractConvert {

    private final Logger logger = LoggerFactory.getLogger(HongKongAccountConvertImpl.class);

    // 数据源帐号姓
    private final String SOURCE_FIRSTNAME = ApplicationUtil.getKey(ThirdpartyConstant.THIRDPARTY_HONGKONG_ACCOUNT_FIRSTNAME);

    // 数据源帐号名
    private final String SOURCE_LASTNAME = ApplicationUtil.getKey(ThirdpartyConstant.THIRDPARTY_HONGKONG_ACCOUNT_LASTNAME);

    /**
     * 根据用户ID查询企业帐号总数
     */
    private final String QUERY_ACCOUNT_COUNT_BY_USER_ID = "SELECT COUNT(1) AS COUNT FROM SD_MA_ACCOUNT WHERE IS_DELETED = '0' AND USER_ID = ?";

    /**
     * 根据登录名模糊查询企业帐号
     */
    private final String QUERY_ACCOUNT_LIST_BY_LOGIN_NAME = "SELECT LOGIN_NAME FROM SD_MA_ACCOUNT WHERE IS_DELETED = '0' AND LOGIN_NAME like ?";

    /**
     * 插入企业帐号
     * <pre>
     * INSERT INTO SD_MA_ACCOUNT(ID,USER_ID,LOGIN_NAME,BASEORG_ID,DEFAULT_P,PRECORD,PRECORD_TIME,ACCOUNT_TYPE,ACCOUNT_STATUS,CREATE_TIME,LAST_DATE,ORDER_NO,IS_DELETED,AUTO_OPEN)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
     * </pre>
     */
    private final String INSERT_ACCOUNT = "INSERT INTO SD_MA_ACCOUNT(ID,USER_ID,LOGIN_NAME,BASEORG_ID,DEFAULT_P,PRECORD,PRECORD_TIME,ACCOUNT_TYPE,ACCOUNT_STATUS,CREATE_TIME,LAST_DATE,ORDER_NO,IS_DELETED,AUTO_OPEN)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    /**
     * 根据用户ID修改企业帐号更新时间
     * <pre>
     * UPDATE SD_MA_ACCOUNT SET LAST_DATE = ? WHERE USER_ID = ?
     * </pre>
     */
    private final String UPDATE_ACCOUNT_BY_USER_ID = "UPDATE SD_MA_ACCOUNT SET LAST_DATE = ? WHERE USER_ID = ?";
    
    /**
     * 根据用户ID删除企业帐号
     * <pre>
     * DELETE FROM SD_MA_ACCOUNT WHERE USER_ID = ?
     * </pre>
     */
    private final String DELETE_ACCOUNT_BY_USER_ID = "DELETE FROM SD_MA_ACCOUNT WHERE USER_ID = ?";

    @Override
    public String getConvertName() {
        return "港中旅人员信息_企业帐号转换";
    }

    @Override
    public void convert(MappingTask task, List<Map<String, Object>> source, List<Map<String, Object>> target) {
        final int sourceSize = source.size();
        final int targetSize = target.size();
        if (sourceSize != targetSize) {
            return;
        }
        
        // 创建连接池
        DatabasePool pool = DatabasePool.getInstance();
        String uuid = pool.create(task.getTargetMapping());
        if(StringUtils.isBlank(uuid)){
            return;
        }
        try {
            Map<String, Object> s;
            Map<String, Object> t;
            for (int i = 0; i < targetSize; i++) {
                s = source.get(i);
                t = target.get(i);
                // 转换数据
                this.execute(uuid, ConnectorConstant.OPERTION_INSERT, s, t);
            }
        } catch (Exception e) {
            logger.info(e.getClass() + " >> " + e.getLocalizedMessage());
        } finally {
            pool.close(uuid);
        }
    }
    
    @Override
    public void convert(MappingTask task, Map<String, Object> source, Map<String, Object> target, String event, Map<String, Object> beforeData) {
        if (null == source || null == target) {
            return;
        }
        DatabasePool pool = DatabasePool.getInstance();
        String uuid = pool.create(task.getTargetMapping());
        if(StringUtils.isBlank(uuid)){
            return;
        }
        try {
            // 转换数据
            this.execute(uuid, event, source, target);
        } catch (Exception e) {
            logger.info(e.getClass() + " >> " + e.getLocalizedMessage());
        } finally {
            pool.close(uuid);
        }
    }

    public void execute(String jdbcTemplateId, String event, Map<String, Object> source, Map<String, Object> target) {
        /**
         * 业务流程
         * 1.将姓和名字段组合为用户姓名
         * 2.创建企业帐号
         * 3.将姓名转换为拼音,设置为企业帐号登录名LOGIN_NAME
         * 4.设置企业帐号中用户USER_ID值
         * 5.采用设置ID为UUID随机串
         */
        // 获取数据库连接
        DatabasePool pool = DatabasePool.getInstance();
        JdbcTemplate jdbc = pool.get(jdbcTemplateId);
        if (null == jdbc) {
            return;
        }
        // 用户ID
        String id = (String) target.get("ID");
        switch (event) {
        case ConnectorConstant.OPERTION_INSERT:
            // 保存企业帐号
            this.insert(jdbc, source, target, id);
            break;
        case ConnectorConstant.OPERTION_UPDATE:
            // 修改企业帐号
            this.update(jdbc, id);
            break;
        case ConnectorConstant.OPERTION_DELETE:
            // 删除企业帐号
            this.delete(jdbc, id);
            break;
        default:
            break;
        }
    }
    
    private void update(JdbcTemplate jdbc, String userId) {
        Timestamp lastDate = new Timestamp(System.currentTimeMillis());
        jdbc.update(UPDATE_ACCOUNT_BY_USER_ID, new Object[] { lastDate, userId });
    }

    private void delete(JdbcTemplate jdbc, String userId) {
        // 根据用户ID删除企业帐号
        jdbc.update(DELETE_ACCOUNT_BY_USER_ID, new Object[] { userId });
    }

    /**
     * 生成企业帐号:san.zhang1
     * @param jdbc 目标源实例
     * @param source 数据源
     * @return 企业帐号
     */
    private String createLoginName(JdbcTemplate jdbc, Map<String, Object> source) {
        try {
            // 1.将帐号转换为拼音
            Object firstname = source.get(SOURCE_FIRSTNAME);
            Object lastname = source.get(SOURCE_LASTNAME);
            StringBuilder account = new StringBuilder();
            String lName = String.valueOf(lastname).replace("　", "").replaceAll("\\s+", "");
            String fName = String.valueOf(firstname).replace("　", "").replaceAll("\\s+", "");
            account.append(PinyinUtil.toPinYinLowerCase(lName)).append(".").append(PinyinUtil.toPinYinLowerCase(fName));

            // 2.查询重复帐号
            Object[] params = new Object[] { account.toString() + "%" };
            List<Map<String, Object>> list = jdbc.queryForList(QUERY_ACCOUNT_LIST_BY_LOGIN_NAME, params);

            // 3.生成自增帐号
            if (null != list && !list.isEmpty()) {
                //思路：截取重复数据最后的字符，如果是数字，就求最大值，如果不是就排除,直到循环结束,最新的自增数=最大值+1
                int start = 0;
                int i = 0;
                String loginName = null;
                String max = null;
                int aLen = account.length();
                for (Map<String, Object> obj : list) {
                    loginName = (String) obj.get("LOGIN_NAME");
                    max = loginName.substring(aLen, loginName.length());
                    if (StringUtils.isEmpty(max) || !StringUtils.isNumeric(max)) {
                        continue;
                    }
                    i = Integer.parseInt(max);
                    start = i > start ? i : start;
                }
                account.append((start + 1));
            }
            return account.toString();
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            logger.error(e.getClass() + " >> " + e.getLocalizedMessage());
        }
        return null;
    }

    /**
     * 插入企业帐号
     * @param jdbc
     * @param sql
     * @param args
     */
    private void insert(JdbcTemplate jdbc, Map<String, Object> source, Map<String, Object> target, String userId) {
        // 1.返回生成的企业帐号:san.zhang1
        String loginName = this.createLoginName(jdbc, source);

        // 2.检查重复数据
        Object[] args = new Object[] { userId };
        Map<String, Object> rs = jdbc.queryForMap(QUERY_ACCOUNT_COUNT_BY_USER_ID, args);
        if (null == rs || 0 < Integer.parseInt(String.valueOf(rs.get("COUNT")))) {
            return;
        }

        // 3.获取证件号(1：大陆身份证；2：香港身份证 3:护照)
        Object id = target.get("PRIVATE_IDENTITYID");
        // 默认密码novell
        String defPwd = "novell";
        if(null != id){
            String idStr = String.valueOf(id);
            int len = idStr.length();
            if(8 <= len){
                // 使用sha1加密算法加密证件后8位作为默认密码
                defPwd = idStr.substring(len - 8, len);
            }
        }
        defPwd = SHA1Util.b64_sha1(defPwd);
        
        /**
         * INSERT INTO SD_MA_ACCOUNT (ID,USER_ID,LOGIN_NAME,BASEORG_ID,DEFAULT_P,PRECORD,PRECORD_TIME,ACCOUNT_TYPE,ACCOUNT_STATUS,CREATE_TIME,LAST_DATE,ORDER_NO,IS_DELETED,AUTO_OPEN)
         * VALUES("123","22","san.zhang",
         * "9A135583FD84B83ABA62E239F9483AB47317B561A4558C40E5F41D5C501B2540","9A135583FD84B83ABA62E239F9483AB47317B561A4558C40E5F41D5C501B2540",
         * "2018-01-17 15:17:12",1,6,"2018-01-17 15:17:12","2018-01-17 15:17:12",1,0,1
         * )
         */
        // 3.插入企业帐号
        Timestamp currentTime = new Timestamp(System.currentTimeMillis());
        Object[] params = new Object[] { UUIDUtil.getUUID(), userId, loginName, "0", defPwd, defPwd, currentTime, 1, 1, currentTime, currentTime, 1, 0, 1 };
        jdbc.update(INSERT_ACCOUNT, params);
    }
    
}
